package org.bigmarketapi.projectreview.DesingMode.codeFlow;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

import static com.google.common.collect.Sets.newConcurrentHashSet;

/**
 * @BelongsProject: ProjectReview
 * @BelongsPackage: org.bigmarketapi.projectreview.DesingMode.codeFlow
 * @Author: dujiaqi
 * @CreateTime: 2024-12-19  23:21
 * @Description: TODO
 * @Version: 1.0
 */
@Slf4j
public abstract class AbilityChain<C extends Context> {
    private Thread thread;

    public AbilityChain(Thread thread) {
        this.thread = thread;
    }

    public abstract C initContext(Request request);

    public Response execute(Request request) {
        C ctx;
        ctx = this.initContext(request);
        if (ctx == null || ctx.getOrders() == null || CollectionUtils.isEmpty(ctx.getNodeMap())) {
            return null;
        }
        final String order = ctx.getOrders();
        final List<List<node>> lists = processOrder(order);
        for (List<node> nodes : lists) {
            final boolean result = nodes.size() > 1 ? concurrentExecute(nodes, ctx) : serialExecute(nodes, ctx);
            if (!result) {
                return new Response("002","FALSE");
            }
        }
        return new Response("000","TRUE");
    }

    private boolean concurrentExecute(List<node> nodes, C ctx) {
        if (CollectionUtils.isEmpty(nodes)) {
            return false;
        }
        //利用CompletableFuture实现并行编排
        final List<node> filterNodes = nodes.stream().filter(Objects::nonNull).toList();
        final CompletableFuture[] futures = filterNodes.stream().map(node -> CompletableFuture.supplyAsync(() -> this.executePerNode(node, ctx))).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(futures).join();
        //另一种： thenApply流水线式的操作，结合函数编程实际操作每个CompletableFuture
        final List<Boolean> joins = CompletableFuture.allOf(futures).thenApply(v -> Arrays.stream(Arrays.stream(futures).map(CompletableFuture::join).toArray(Boolean[]::new)).toList()).join();
        final boolean contains = joins.contains(Boolean.FALSE);
        //另一种： join+stream分别操作
        final List<Boolean> booleans = Arrays.stream(Arrays.stream(futures).map(CompletableFuture::join).toArray(Boolean[]::new)).toList();
        return !booleans.contains(Boolean.FALSE);
    }

    public Boolean serialExecute(List<node> nodes, C ctx) {
        //已经找到第一个false的match情况
        final boolean match = nodes.stream().filter(Objects::nonNull).anyMatch(node -> {
            return !this.executePerNode(node, ctx);
        });
        return !match;
    }

    private boolean executePerNode(node node, C ctx) {
        if (node == null || ctx == null) {
            return false;
        }
        final boolean isContinue = node.execute();
        if (!isContinue) {
            ctx.track("");
        }
        return isContinue;
    }

    public List<List<node>> processOrder(String order) {
        if (order == null) {
            return null;
        }
        // 去除外层方括号
        String innerContent = order.substring(1, order.length() - 1).trim();

        // 使用正则表达式分割内部列表
        String[] parts = innerContent.split("\\],\\[");
        final List<List<node>> lists = Arrays.stream(parts).filter(s -> !s.isEmpty()).map(s -> {
            String part = s.trim();
            if (part.startsWith("[")) {
                part = part.substring(1).trim();
            }
            if (part.endsWith("]")) {
                part = part.substring(0, part.length() - 1).trim();
            }
            return Arrays.stream(part.split(",")).map(str -> new node(str.trim())).toList();
        }).toList();
        log.info("list: {}", JSON.toJSONString(lists));
        // 创建一个列表来存储最终的结果
        List<List<String>> resultLists = new ArrayList<>();
        return lists;
    }
}
